package net.entelijan.cobean.table;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JTable;
import javax.swing.ListSelectionModel;

import net.entelijan.cobean.core.ColumnDesc;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapper;

@SuppressWarnings("unchecked")
class SortableBeansTableModel<T> extends AbstractBeansTableModel<T> {

	private static Log log = LogFactory.getLog(SortableBeansTableModel.class);

	private LinkedList<SortItem> sortItems;

	public SortableBeansTableModel(Collection<?> beans,
			List<ColumnDesc> columnDescs, JTable table,
			LinkedList<SortItem> sortItems) {
		super(beans, columnDescs, table);
		this.sortItems = sortItems;
	}

	private static final long serialVersionUID = 1L;

	public void sort(int column) {
		ListSelectionModel selectionModel = this.table.getSelectionModel();
		int leadSelectionIndex = selectionModel.getLeadSelectionIndex();
		BeanWrapper selectedRow = null;
		if (leadSelectionIndex >= 0) {
			selectedRow = this.beans.get(leadSelectionIndex);
		}
		SortItem latestSortItem = arrangeSortItems(column);
		ColumnDesc desc = this.columnDescs.get(latestSortItem.getIndex());
		if (desc.isSortable()) {
			Collections.sort(this.beans, new PropertiesSorter(desc
					.getPropertyName(), latestSortItem.isDescending()));
		}
		if (selectedRow != null) {

		}
		if (selectedRow != null) {
			int i = this.beans.indexOf(selectedRow);
			if (i >= 0) {
				selectionModel.clearSelection();
				selectionModel.setSelectionInterval(i, i);
			}
		}
		this.table.repaint();
	}

	private SortItem arrangeSortItems(int index) {
		SortItem item = findSortItem(index);
		if (item == null) {
			item = new SortItem(index, true);
		} else {
			item.setDescending(!item.isDescending());
			this.sortItems.remove(item);
		}
		this.sortItems.addFirst(item);
		log.debug("[arrangeSortItems] " + this.sortItems);
		return item;
	}

	private SortItem findSortItem(int index) {
		SortItem re = null;
		for (SortItem item : this.sortItems) {
			if (item.getIndex() == index) {
				re = item;
				break;
			}
		}
		return re;
	}

	public List<T> getSelection() {
		ArrayList<T> re = new ArrayList<T>();
		int[] selIndices = this.table.getSelectedRows();
		for (int i : selIndices) {
			T item = (T) this.beans.get(i).getWrappedInstance();
			re.add(item);
		}
		return re;

	}

}
